[GCP] Cloud Deployment ManagerでCloud Functionsをデプロイしてみた
Google Cloud Deployment ManagerでCloud Functionsのデプロイをやってみました。Cloud Functionsにコードをデプロイするため、Pythonテンプレートを利用してCloud BuildでCloud StorageへのZIPファイルのアップロードを実装しています。
事前準備
Cloud Deployment Managerでリソースをデプロイする際にgcloudコマンドを使用します。gcloud CLIはCloud SDKをインストールすることで利用できるようになります。Cloud SDKの導入方法は次のブログが参考になりました。
環境
項目 | 内容 |
---|---|
OS | macOS Catalina 10.15.4(19E287) |
Python | 3.7.0 |
Cloud SDK | 280.0.0 |
ディレクトリ構成
ディレクトリ構成は以下の通りです。Cloud Functionsのソースコードと構成ファイルやPythonテンプレートを分けています。
・ ├─ src │ ├─ hello-world │ │ └─ index.js │ └─ welcome │ └─ index.js └─ templates ├─ cloud-functions.py └─ cloud-functions.yaml
Cloud Functionsのソースコード
シンプルなメッセージを返す2つの関数を実装します。
exports.handler = (req, res) => { res.status(200).send({ message: "Hello World!", time: new Date(), }); };
exports.handler = (req, res) => { res.status(200).send({ message: "Welcome!", time: new Date(), }); };
Pythonテンプレート
Pythonテンプレートは各リソース定義の雛形です。Cloud FunctionsのデプロイではソースコードをZIPファイルにまとめて、Cloud Storageのバケットにアップロードする必要があります。これをPythonテンプレートで実装します。
import zipfile import io import base64 import hashlib def GenerateConfig(context): in_memory_output_file = io.BytesIO() zip_file = zipfile.ZipFile( in_memory_output_file, mode='w', compression=zipfile.ZIP_DEFLATED) for imp in context.imports: if imp.startswith(context.properties['codeLocation']): zip_file.writestr( imp[len(context.properties['codeLocation']):], context.imports[imp]) zip_file.close() content = base64.b64encode(in_memory_output_file.getvalue()) m = hashlib.md5() m.update(content) source_archive_url = 'gs://%s/%s' % ( context.properties['codeBucket'], m.hexdigest() + '.zip') cmd = "echo '%s' | base64 -d > /function/function.zip;" % ( content.decode('ascii')) volumes = [{'name': 'function-code', 'path': '/function'}] upload_function_code = { 'action': 'gcp-types/cloudbuild-v1:cloudbuild.projects.builds.create', 'name': context.properties['function'] + '-upload-function-code', 'properties': { 'steps': [{ 'name': 'ubuntu', 'args': ['bash', '-c', cmd], 'volumes': volumes, }, { 'name': 'gcr.io/cloud-builders/gsutil', 'args': ['cp', '/function/function.zip', source_archive_url], 'volumes': volumes }], 'timeout': '120s' }, 'metadata': { 'runtimePolicy': ['UPDATE_ON_CHANGE'] } } cloud_function = { 'type': 'gcp-types/cloudfunctions-v1:projects.locations.functions', 'name': context.properties['function'] + '-cloud-function', 'properties': { 'parent': f"projects/{context.env['project']}/locations/{context.properties['location']}", 'function': context.properties['function'], 'sourceArchiveUrl': source_archive_url, 'entryPoint': context.properties['entryPoint'], 'httpsTrigger': {}, 'timeout': context.properties['timeout'], 'availableMemoryMb': context.properties['memory'], 'runtime': context.properties['runtime'] }, 'metadata': { 'dependsOn': [context.properties['function'] + '-upload-function-code'] } } return { 'resources': [upload_function_code, cloud_function] }
Pythonテンプレートでは、GenerateConfig
またはgenerate_config
という名前のメソッドを定義します。context
オブジェクトには、環境に関するメタデータや構成ファイルのプロパティが渡されます。
再利用可能なテンプレートについて | Google Cloud
構成ファイル
構成ファイルではPythonテンプレートを読み込んでリソースを定義します。resources
のtype
にPythonテンプレートを指定できます。なお、使用するファイルは全てimports
に書く必要があります。
imports: - path: ../src/hello-world/index.js - path: ../src/welcome/index.js - path: cloud-functions.py resources: - type: cloud-functions.py name: hello-world properties: function: hello-world codeLocation: ../src/hello-world/ codeBucket: [ソースコードをアップロードするバケットの名前] location: asia-northeast1 timeout: 60s runtime: nodejs8 memory: 256 entryPoint: handler - type: cloud-functions.py name: welcome properties: function: welcome codeLocation: ../src/welcome/ codeBucket: [ソースコードをアップロードするバケットの名前] location: asia-northeast1 timeout: 60s runtime: nodejs8 memory: 256 entryPoint: handler
properties
に定義した値はPythonテンプレートに渡されます。例えばcodeLocation
はPythonテンプレートでcontext.properties['codeLocation']
のように取得できます。
codeBucket
は後でソースコードのアップロード先のバケットを作成した際にバケットの名前に変更します。
デプロイ
Cloud Buildを使いますので有効になっていない場合は有効化します。
Cloud StorageでCloud Functionsのソースコードをアップロードするバケットを作成します。
デプロイ先のプロジェクトを gcloud コマンドで指定します。
gcloud config set project [PROJECT_ID]
作成した構成ファイルを使用して gcloud コマンドでデプロイします。
gcloud deployment-manager deployments create cloud-functions --config templates/cloud-functions.yaml
Cloud Deployment Managerのコンソールでデプロイの詳細を確認できます。
デプロイが完了するとCloud Functionsのコンソールに表示されます。
Cloud Functionsのテストを実行して「Hello World!」が出力されることを確認します。
後片付け
作成したリソースに対しては課金が発生するため、忘れずに削除します。
gcloud deployment-manager deployments delete cloud-functions
Cloud StorageのバケットはGCPのコンソールから手動で削除します。
まとめ
Cloud Deployment ManagerではPythonテンプレートを利用することで、構成ファイルでリソースをシンプルに定義できることがわかりました。次はCloud APIなど他のリソースとCloud Functionsを組み合わせた使い方について学習したいと考えています。
構成ファイルやPythonテンプレートはGitHubでもソースコードを公開しています。